package net.youdi.gateway.config;

import net.youdi.gateway.handler.GateWayJsonExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

import java.util.List;

/**
 * @author scl.BlueOcean
 * @version 1.0
 * @date 2018年09月28 16:51
 * @description webflux全局异常处理器配置配置
 * 由于webflux的函数式编程方式中不能通过controllerAdvice只能通过每个RouterFunction中添加filter的方式实现异常处理，
 * 这里通过注入一个自定义ErrorWebExceptionHandler来达到全局异常处理的目的
 */
@Configuration
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
public class ErrorHandlerConfiguration {
    @Autowired
    private ServerProperties serverProperties;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private ResourceProperties resourceProperties;
    @Autowired
    private ObjectProvider<List<ViewResolver>> viewResolversProvider;
    @Autowired
    private ServerCodecConfigurer serverCodecConfigurer;

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {

        GateWayJsonExceptionHandler exceptionHandler = new GateWayJsonExceptionHandler(
                errorAttributes, this.resourceProperties,
                this.serverProperties.getError(), this.applicationContext);
        exceptionHandler.setViewResolvers(this.viewResolversProvider.getIfAvailable());
        exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
        exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
        return exceptionHandler;
    }
}
